Dropbox API client to deal with directory listing.

Guilherme J. Tramontina 10 years ago
parent
commit
70bb48b295
2 changed files with 102 additions and 2 deletions
  1. 20 2
      app/models/agents/dropbox_watch_agent.rb
  2. 82 0
      spec/models/agents/dropbox_watch_agent_spec.rb

+ 20 - 2
app/models/agents/dropbox_watch_agent.rb

@@ -40,7 +40,6 @@ module Agents
40 40
     def check
41 41
       api = DropboxAPI.new(interpolated[:access_token])
42 42
       current_contents = api.dir(interpolated[:dir_to_watch])
43
-
44 43
       diff = DropboxDirDiff.new(previous_contents, current_contents)
45 44
       create_event(payload: diff.to_hash) unless previous_contents.nil? || diff.empty?
46 45
 
@@ -66,13 +65,32 @@ module Agents
66 65
     # == Auxiliary classes ==
67 66
 
68 67
     class DropboxAPI
68
+      class ResourceNotFound < RuntimeError; end
69
+
70
+      include HTTParty
71
+      base_uri 'https://api.dropbox.com/1'
72
+
69 73
       def initialize(access_token)
74
+        @options = { query: { access_token: access_token } }
75
+      end
76
+
77
+      def dir(to_watch)
78
+        options = @options.deep_merge({ query: { list: true } })
79
+        response = self.class.get("/metadata/auto#{to_watch}", options)
80
+        raise ResourceNotFound.new(to_watch) if response.not_found?
81
+        JSON.parse(response)['contents'].map { |entry| slice_json(entry, :path, :rev, :modified) }
82
+      end
83
+
84
+      private
85
+
86
+      def slice_json(json, *keys)
87
+        keys.each_with_object({}){|key, hash| hash[key] = json[key.to_s]}
70 88
       end
71 89
     end
72 90
 
73 91
     class DropboxDirDiff
74 92
       def initialize(previous, current)
75
-        @previous, @current = [previous, current]
93
+        @previous, @current = [previous || [], current || []]
76 94
       end
77 95
 
78 96
       def empty?

+ 82 - 0
spec/models/agents/dropbox_watch_agent_spec.rb

@@ -154,6 +154,88 @@ describe Agents::DropboxWatchAgent do
154 154
         expect(diff_hash[:updated]).to eq [ { path: '1.json', rev: '2' } ]
155 155
       end
156 156
 
157
+      context 'when the previous value is not defined' do
158
+        it 'considers all additions' do
159
+          diff_hash = Agents::DropboxWatchAgent::DropboxDirDiff.new(nil, current).to_hash
160
+          expect(diff_hash[:added]).to eq current
161
+          expect(diff_hash[:removed]).to eq []
162
+          expect(diff_hash[:updated]).to eq []
163
+        end
164
+      end
165
+
166
+      context 'when the current value is not defined' do
167
+        it 'considers all removals' do
168
+          diff_hash = Agents::DropboxWatchAgent::DropboxDirDiff.new(previous, nil).to_hash
169
+          expect(diff_hash[:added]).to eq []
170
+          expect(diff_hash[:removed]).to eq previous
171
+          expect(diff_hash[:updated]).to eq []
172
+        end
173
+      end
174
+    end
175
+  end
176
+
177
+  describe Agents::DropboxWatchAgent::DropboxAPI do
178
+    let(:dir_to_watch) { '/my/dropbox/dir' }
179
+    let(:access_token) { '70k3n' }
180
+    let(:api_url) { "https://api.dropbox.com/1/metadata/auto#{dir_to_watch}?access_token=#{access_token}&list=true" }
181
+
182
+    describe '#dir' do
183
+
184
+      context 'when the provided path exists' do
185
+        before do
186
+          stub_request(:get, api_url).to_return(body: JSON.dump({
187
+            contents: [
188
+                {
189
+                    bytes: 0,
190
+                    icon: "folder",
191
+                    is_dir: true,
192
+                    modified: "Mon, 11 Mar 2013 15:41:44 +0000",
193
+                    path: "#{dir_to_watch}/1.json",
194
+                    rev: "1",
195
+                    revision: 14743,
196
+                    root: "dropbox",
197
+                    size: "0 bytes",
198
+                    thumb_exists: false
199
+                },
200
+                {
201
+                    bytes: 0,
202
+                    icon: "folder",
203
+                    is_dir: true,
204
+                    modified: "Mon, 12 Mar 2013 15:41:44 +0000",
205
+                    path: "#{dir_to_watch}/2.json",
206
+                    rev: "4",
207
+                    revision: 113022,
208
+                    root: "dropbox",
209
+                    size: "0 bytes",
210
+                    thumb_exists: false
211
+                }
212
+            ],
213
+            some: "other",
214
+            things: "we",
215
+            dont: "need"
216
+          }))
217
+        end
218
+
219
+        it 'trims down the attributes of the response to our needs' do
220
+          dir_list = Agents::DropboxWatchAgent::DropboxAPI.new(access_token).dir(dir_to_watch)
221
+          expect(dir_list).to eq [
222
+            { path: "#{dir_to_watch}/1.json", rev: '1', modified: 'Mon, 11 Mar 2013 15:41:44 +0000' },
223
+            { path: "#{dir_to_watch}/2.json", rev: '4', modified: 'Mon, 12 Mar 2013 15:41:44 +0000' }
224
+          ]
225
+        end
226
+      end
227
+
228
+      context 'when the provided path does not exist' do
229
+        before { stub_request(:get, api_url).to_return(status: 404, body: '{"error": "Not Found"}') }
230
+
231
+        it 'raises a ResourceNotFound error' do
232
+          expect {
233
+            Agents::DropboxWatchAgent::DropboxAPI.new(access_token).dir(dir_to_watch)
234
+          }.to raise_error(Agents::DropboxWatchAgent::DropboxAPI::ResourceNotFound, dir_to_watch)
235
+        end
236
+      end
237
+
157 238
     end
239
+
158 240
   end
159 241
 end